package com.device.service;

import com.alibaba.fastjson.JSONObject;
import com.device.dataobject.vo.ResultVO;
import com.device.entity.*;
import com.device.enums.CacheEnum;
import com.device.repository.*;
import com.device.util.ResultVOUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.*;



@Service
public class AdminService {
    private final UserRepository userRepository;
    private final DeviceRepository deviceRepository;
    private final RegisterRepository registerRepository;
    private final PostRepository postRepository;
    private final RentRepository rentRepository;
    private final UserDeviceRepository userDeviceRepository;
    private final RedisTemplate<String,Object> redisTemplate;

    private static final HashSet<String> areaSet = new HashSet<>();

    // Static initializer block to populate the areaSet
    static {
        // Insert 5 area records into the set
        areaSet.add("苏州");
        areaSet.add("北京");
        areaSet.add("南京");
        areaSet.add("广州");
        areaSet.add("浙江");
    }



    @Autowired
    public AdminService(UserRepository userRepository, DeviceRepository deviceRepository, RegisterRepository registerRepository, PostRepository postRepository, RentRepository rentRepository, UserDeviceRepository userDeviceRepository, RedisTemplate<String,Object> redisTemplate) {

        this.userRepository = userRepository;
        this.deviceRepository = deviceRepository;
        this.registerRepository = registerRepository;
        this.postRepository = postRepository;
        this.rentRepository = rentRepository;
        this.userDeviceRepository = userDeviceRepository;
        this.redisTemplate = redisTemplate;
    }


    public ResultVO handleApproveRentOperation(JSONObject jsonObject) {
        try {
            Integer rentId = jsonObject.getInteger("rent_id");
            Rent rent = rentRepository.findById(rentId)
                    .orElseThrow(() -> new NoSuchElementException("订单不存在"));

            rent.setStatus("审核通过");
            rentRepository.save(rent);

            String area = rent.getDevice_area();
            Integer deviceCount = rent.getDevice_num();
            Device device = getDeviceByName(rent.getDeviceName());
            if (areaSet.contains(area)&&deviceCount>0){
            updateDeviceIdleCount(device, area, deviceCount);
            selectAndHandleUserDevices(area, device.getDeviceName(), deviceCount, rent);}
            return ResultVOUtil.returnSuccess();
            // Add additional processing or notifications as needed

        } catch (NoSuchElementException e) {
            // Handle exception (e.g., log error, return error response)
        }
        return ResultVOUtil.returnFail(402,"参数错误");
    }

    private Device getDeviceByName(String deviceName) {
        Device device = deviceRepository.findByDeviceName(deviceName);
        if (device == null) {
            throw new NoSuchElementException("设备不存在");
        }
        return device;
    }

    public void updateDeviceIdleCount(Device device, String area, int deviceCount) {
        device.getIdle_device().merge(area, -deviceCount, Integer::sum);
        device.getIdle_device().merge("空闲",-deviceCount,Integer::sum);
        deviceRepository.save(device);
    }

    private void selectAndHandleUserDevices(String area, String deviceName, int deviceCount, Rent rent) {
        List<UserDevice> userDevices = userDeviceRepository.findByAreaAndDeviceNameAndStatus(area, deviceName, true);
        int selectedCount = Math.min(deviceCount, userDevices.size());

        List<UserDevice> selectedUserDevices = userDevices.subList(0, selectedCount);
        for (UserDevice userDevice : selectedUserDevices) {
            // 处理符合条件的设备
            userDevice.setStatus(false);
            userDevice.setRentUser(rent.getUser());
            userDevice.setRentInstitute(rent.getRentInstitute());
            userDevice.setEndTime(rent.getEndTime());
            userDevice.setRentId(rent.getId());
        }
        userDeviceRepository.saveAll(selectedUserDevices);
    }

    public void handleRejectRentOperation(JSONObject jsonObject) {
        try {
            Integer rentId = jsonObject.getInteger("rent_id");
            Rent rent = getRentById(rentId);
            rent.setStatus("拒绝");
            rentRepository.save(rent);
        } catch (NoSuchElementException e) {
            // 处理订单不存在的情况
            e.printStackTrace();
        }
    }

    public void handleRejectPostOperation(JSONObject jsonObject) {
        try {
            Integer postId = jsonObject.getInteger("post_id");
            Post post = getPostById(postId);
            post.setStatus("拒绝");
            postRepository.save(post);
        } catch (NoSuchElementException e) {
            // 处理订单不存在的情况
            e.printStackTrace();
        }
    }

    public void handleEditPostOperation(JSONObject jsonObject) {
        try {
            Integer postId = jsonObject.getInteger("post_id");
            Post post = getPostById(postId);
            setPostInfo(jsonObject,post);
        } catch (NoSuchElementException e) {
            // 处理订单不存在的情况
            e.printStackTrace();
        }
    }

    public void handleEditRentOperation(JSONObject jsonObject) {
        try {
            Integer rentId = jsonObject.getInteger("rent_id");
            Rent rent = getRentById(rentId);
            setRentInfo(jsonObject,rent);
        } catch (NoSuchElementException e) {
            // 处理订单不存在的情况
            e.printStackTrace();
        }
    }

    public ResultVO handleApprovePostOperation(JSONObject jsonObject) {
        try {
            Integer postId = jsonObject.getInteger("post_id");
            Post post = getPostById(postId);
            post.setStatus("审核通过");
            postRepository.save(post);
            String area = post.getDevice_area();
            Integer num = post.getDevice_num();
            Device device = getDeviceByName(post.getDeviceName());
            if (areaSet.contains(area) && num > 0){
            editDeviceNum(device,area,num);
            deviceRepository.save(device);
            saveUserDevices(num, area, post.getDeviceName(), post.getUser(), post.getInstituteName(), post.getRentPrice(),postId);
            return ResultVOUtil.returnSuccess();
            }
        } catch (NoSuchElementException e) {
            // 处理订单不存在的情况
            e.printStackTrace();
        }
        return ResultVOUtil.returnFail(402,"参数错误");
    }

    private Rent getRentById(Integer rentId) {
        return rentRepository.findById(rentId)
                .orElseThrow(() -> new NoSuchElementException("订单不存在"));
    }

    private Post getPostById(Integer postId) {
        return postRepository.findById(postId)
                .orElseThrow(() -> new NoSuchElementException("订单不存在"));
    }

    private void saveUserDevices(int num, String area, String deviceName, User user, String institute, Integer rentPrice,Integer postId) {
        for (int i = 0; i < num; i++) {
            UserDevice userDevice = new UserDevice();
            userDevice.setArea(area);
            userDevice.setDeviceName(deviceName);
            userDevice.setUser(user);
            userDevice.setInstituteName(institute);
            userDevice.setRentPrice(rentPrice);
            userDevice.setPostId(postId);
            userDeviceRepository.save(userDevice);
        }
    }

    public CompletableFuture<ResultVO> handleAllRentOperation(JSONObject jsonObject) {

        Pageable pageable = getPageable(jsonObject);
        return CompletableFuture.supplyAsync(() -> rentRepository.findAll(pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }

    public CompletableFuture<ResultVO> handleAllPostOperation(JSONObject jsonObject) {

        Pageable pageable = getPageable(jsonObject);
        return CompletableFuture.supplyAsync(() -> postRepository.findAll(pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }

    public Pageable getPageable(JSONObject jsonObject){
        Integer page =  jsonObject.getInteger("page");
        Integer size = jsonObject.getInteger("size");
        return PageRequest.of(page - 1, size);
    }

    public void handleDeleteUserOperation(JSONObject jsonObject) {
        Integer deleteUserId = jsonObject.getInteger("user_id");
        userRepository.deleteById(deleteUserId);
    }

    public void handlePassUserOperation(JSONObject jsonObject) {
        Integer passUserId = jsonObject.getInteger("user_id");
        userRepository.findById(passUserId)
                .ifPresent(user -> {
                    user.setIsRegister(true);
                    userRepository.save(user);
                });
    }

    public void handleCancelPUserOperation(JSONObject jsonObject) {
        Integer cancelPUserId = jsonObject.getInteger("user_id");
        userRepository.findById(cancelPUserId)
                .ifPresent(user -> {
                    user.setIsRegister(false);
                    userRepository.save(user);
                });
    }

    public void handleCancelAUserOperation(JSONObject jsonObject) {
        Integer cancelAUserId = jsonObject.getInteger("user_id");
        userRepository.findById(cancelAUserId)
                .ifPresent(user -> {
                    user.setIsAdmin(false);
                    userRepository.save(user);
                });
    }

    public void handleAdminUserOperation(JSONObject jsonObject) {
        Integer adminUserId = jsonObject.getInteger("user_id");
        userRepository.findById(adminUserId)
                .ifPresent(user -> {
                    user.setIsAdmin(true);
                    userRepository.save(user);
                });
    }

    public CompletableFuture<ResultVO> handleRegisteringOperation(JSONObject jsonObject) {
        Pageable pageable = getPageable(jsonObject);
        return CompletableFuture.supplyAsync(() -> registerRepository.findAll(pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }

    public CompletableFuture<ResultVO> handleRegisteredOperation(JSONObject jsonObject) {
        Pageable pageable = getPageable(jsonObject);
        return CompletableFuture.supplyAsync(() -> userRepository.RegisteredOrNot(true, pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }

    public CompletableFuture<ResultVO> handleUnregisteredOperation(JSONObject jsonObject) {
        Pageable pageable = getPageable(jsonObject);
        return CompletableFuture.supplyAsync(() -> userRepository.RegisteredOrNot(false, pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }

    public CompletableFuture<ResultVO> handleCountOperation() {

        // 尝试从Redis缓存中获取用户数量
        Long cachedCount = (Long) redisTemplate.opsForValue().get(CacheEnum.USER_COUNT.name());

        if (cachedCount != null) {
            // 缓存命中，直接返回缓存的结果
            return CompletableFuture.completedFuture(ResultVOUtil.returnSuccess(cachedCount));
        } else {
            // 异步执行数据库查询用户数量的操作
            return CompletableFuture.supplyAsync(userRepository::count)
                    .thenApply(count -> {
                        // 将查询结果存入Redis缓存
                        redisTemplate.opsForValue().set(CacheEnum.USER_COUNT.name(), count);
                        return ResultVOUtil.returnSuccess(count);
                    })
                    .exceptionally(e -> {
                        // 异常处理
                        e.printStackTrace();
                        return ResultVOUtil.returnFail();
                    });
        }
    }

    public void handleEditOperation(JSONObject jsonObject) {
        Integer deviceId = jsonObject.getInteger("device_id");
        deviceRepository.findById(deviceId)
                .ifPresent(device -> setDeviceProperties(jsonObject, device));
    }

    public void handleAddOperation(JSONObject jsonObject) {
        Device device = new Device();
        setDeviceProperties(jsonObject, device);
    }

    public void handleDeleteOperation(JSONObject jsonObject) {
        Integer deletedId = jsonObject.getInteger("device_id");
        deviceRepository.findById(deletedId)
                .ifPresent(deviceRepository::delete);
    }

    public CompletableFuture<ResultVO> handleAllUDOperation(JSONObject jsonObject) {

        Pageable pageable = getPageable(jsonObject);
        String deviceName = jsonObject.getString("deviceName");
        return CompletableFuture.supplyAsync(() -> userDeviceRepository.findByDeviceName(deviceName,pageable))
                .thenApply(data -> ResultVOUtil.returnSuccess(data.getContent()))
                .exceptionally(e -> {
                    // 异常处理
                    e.printStackTrace();
                    return ResultVOUtil.returnFail();
                });
    }


    public void handleEditUDOperation(JSONObject jsonObject,Integer userId) {
        Integer deviceId = jsonObject.getInteger("device_id");
        Optional<UserDevice> optionalDevice = userDeviceRepository.findById(deviceId);
        optionalDevice.ifPresent(device -> setUserDeviceProperties(jsonObject, device, userId));
    }

    public void handleAddUDOperation(JSONObject jsonObject, Integer userId) {
        Integer addNum = jsonObject.getInteger("add_num");
        String area = jsonObject.getString("area");
        String deviceName = jsonObject.getString("deviceName");

        Device device = deviceRepository.findByDeviceName(deviceName);
        if (device != null) {
            for (int i = 0; i < addNum; i++) {
                UserDevice deviceToAdd = new UserDevice();
                setUserDeviceProperties(jsonObject, deviceToAdd, userId);
                userDeviceRepository.save(deviceToAdd);
            }
            editDeviceNum(device,area,addNum);
            deviceRepository.save(device);
        }
    }

    public void handleDeleteUDOperation(JSONObject jsonObject) {
        List<Integer> deleteIds = jsonObject.getJSONArray("deleteIds").toJavaList(Integer.class);
        List<UserDevice> userDevicesToDelete = userDeviceRepository.findAllById(deleteIds);
        for (UserDevice userDevice:userDevicesToDelete){
            Device device = deviceRepository.findByDeviceName(userDevice.getDeviceName());
            editDeviceNum(device,userDevice.getArea(),-1);
        }
        userDeviceRepository.deleteInBatch(userDevicesToDelete);
    }

    public void editDeviceNum(Device device,String area,Integer addNum){
        device.getTotal_device().merge(area, addNum,Integer::sum);
        device.getTotal_device().merge("总计", addNum,Integer::sum);
        device.getIdle_device().merge(area, addNum,Integer::sum);
        device.getIdle_device().merge("空闲", addNum,Integer::sum);
    }


    private void setUserDeviceProperties(JSONObject jsonObject, UserDevice device, Integer userId) {
        if (jsonObject.get("instituteName") != null) {
            device.setInstituteName(jsonObject.getString("instituteName"));
        }
        if (jsonObject.get("area") != null) {
            device.setArea(jsonObject.getString("area"));
        }
        if (jsonObject.get("deviceName") != null) {
            device.setDeviceName(jsonObject.getString("deviceName"));
        }
        if (jsonObject.get("rent_price") != null) {
            device.setRentPrice(jsonObject.getInteger("rent_price"));
        }
        if (userId != null) {
            Optional<User> optionalUser = userRepository.findById(userId);
            optionalUser.ifPresent(device::setUser);
        }
        userDeviceRepository.save(device);
    }

    private void setDeviceProperties(JSONObject jsonObject, Device device) {
        if (jsonObject.get("device_info") != null) {

            device.setDevice_info(jsonObject.getString("device_info"));
        }
        if (jsonObject.get("device_advantage") != null) {
            device.setDevice_advantage(jsonObject.getString("device_advantage"));
        }
        if (jsonObject.get("deviceName") != null) {
            device.setDeviceName(jsonObject.getString("deviceName"));
        }
        if (jsonObject.get("device_image") != null) {
            device.setDevice_image(jsonObject.getString("device_image"));
        }
        deviceRepository.save(device);

        // 更新缓存
        updateDeviceCache(device);
    }

    private void setPostInfo(JSONObject jsonObject, Post post) {
        if (jsonObject.get("device_area") != null) {

            post.setDevice_area(jsonObject.getString("device_area"));
        }
        if (jsonObject.get("rent_price") != null) {
            post.setRentPrice(jsonObject.getInteger("price"));
        }
        if (jsonObject.get("deviceName") != null) {
            post.setDeviceName(jsonObject.getString("deviceName"));
        }
        if (jsonObject.get("device_num") != null) {
           post.setDevice_num(jsonObject.getInteger("device_num"));
        }
        postRepository.save(post);

    }

    private void setRentInfo(JSONObject jsonObject, Rent rent) {
        if (jsonObject.get("device_area") != null) {
            rent.setDevice_area(jsonObject.getString("device_area"));
        }

        if (jsonObject.get("deviceName") != null) {
            rent.setDeviceName(jsonObject.getString("deviceName"));
        }
        if (jsonObject.get("device_num") != null) {
            rent.setDevice_num(jsonObject.getInteger("device_num"));
        }
        rentRepository.save(rent);

    }



    private void updateDeviceCache(Device device) {

        // 从Redis缓存中获取设备名称列表
        List<String> cachedDeviceNames = (List<String>) redisTemplate.opsForValue().get(CacheEnum.DEVICE_NAMES.name());

        if (cachedDeviceNames != null) {
            // 更新设备名称列表
            cachedDeviceNames.remove(device.getDeviceName());
            cachedDeviceNames.add(device.getDeviceName());

            // 将更新后的设备名称列表存入Redis缓存中
            redisTemplate.opsForValue().set(CacheEnum.DEVICE_NAMES.name(), cachedDeviceNames);
        }
    }



}